package com.ruoyi.project.system.service.impl;

import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.system.domain.ResTable;
import com.ruoyi.project.system.domain.PerQueryList;
import com.ruoyi.project.system.domain.dto.ResWithQueryDTO;
import com.ruoyi.project.system.mapper.ResTableMapper;
import com.ruoyi.project.system.mapper.PerQueryListMapper;
import com.ruoyi.project.system.service.IReservationService;
import com.ruoyi.project.system.service.ITempWeekDailyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Service
public class ReservationServiceImpl implements IReservationService {

    // 日志框架（确保调试日志能输出）
    private static final Logger logger = LoggerFactory.getLogger(ReservationServiceImpl.class);

    @Autowired
    private ResTableMapper resTableMapper;

    @Autowired
    private PerQueryListMapper perQueryListMapper;

    // 关键修复：注入 ITempWeekDailyService 实例（而非直接用类名调用）
    @Autowired
    private ITempWeekDailyService tempWeekDailyService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitResAndQuery(ResWithQueryDTO dto) {
        try {
            // 1. 获取登录用户ID（原逻辑不变）
            Long userId = SecurityUtils.getUserId();
            if (userId == null) {
                logger.error("未登录或登录态失效");
                throw new RuntimeException("未登录或登录态失效，请重新登录！");
            }

            // 2. 调试日志：输出接收的answer1~answer10（原逻辑不变）
            logger.info("===== 调试日志：读取到的问卷答案（answer1~answer10） =====");
            logger.info("answer1：{}", formatAnswer(dto.getAnswer1()));
            logger.info("answer2：{}", formatAnswer(dto.getAnswer2()));
            logger.info("answer3：{}", formatAnswer(dto.getAnswer3()));
            logger.info("answer4：{}", formatAnswer(dto.getAnswer4()));
            logger.info("answer5：{}", formatAnswer(dto.getAnswer5()));
            logger.info("answer6：{}", formatAnswer(dto.getAnswer6()));
            logger.info("answer7：{}", formatAnswer(dto.getAnswer7()));
            logger.info("answer8：{}", formatAnswer(dto.getAnswer8()));
            logger.info("answer9：{}", formatAnswer(dto.getAnswer9()));
            logger.info("answer10：{}", formatAnswer(dto.getAnswer10()));
            logger.info("======================================================");

            // 核心逻辑：用前端传递的 skipQuery 控制 queryIs
            // 前端 skipQuery = "true" → 跳过问卷 → queryIs=0；skipQuery = "false" → 填写问卷 → queryIs=1
            boolean isSkipQuery = "true".equals(dto.getSkipQuery());
            int queryIs = isSkipQuery ? 0 : 1;

            // 调试日志：输出 queryIs 计算结果
            logger.info("===== 调试日志：queryIs 计算结果 =====");
            logger.info("前端传递的 skipQuery：{}", dto.getSkipQuery());
            logger.info("是否跳过问卷：{}", isSkipQuery);
            logger.info("最终 queryIs 赋值：{}", queryIs);
            logger.info("=====================================");

            // 3. 构建 ResTable（原逻辑不变）
            ResTable resTable = new ResTable();
            String resId = "RES_" + userId + "_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(24);
            resTable.setResId(resId);
            resTable.setUserId(userId);
            resTable.setCreateTime(new Date());
            resTable.setResolve(0); // 默认值0（原逻辑不变）
            resTable.setQueryIs(queryIs); // 用 skipQuery 计算后的 queryIs

            // 4. 其他字段赋值（原逻辑不变）
            resTable.setName(dto.getName().trim());
            resTable.setIdentity(dto.getIdentity().trim());
            resTable.setPhone(dto.getPhone().trim());
            resTable.setDepartmentId(Long.parseLong(dto.getDepartmentId().trim()));
            resTable.setDoctor(dto.getDoctor().trim());

            // 5. 时间格式转换（原逻辑不变）
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date appointmentDatetime = sdf.parse(dto.getDatetime().trim());
            resTable.setDatetime(appointmentDatetime);

            // 6. 调试日志：输出存入数据库的核心字段（原逻辑不变）
            logger.info("===== 调试日志：存入数据库的核心字段 =====");
            logger.info("resolve：{}", resTable.getResolve());
            logger.info("queryIs：{}", resTable.getQueryIs());
            logger.info("resId（预约单号）：{}", resTable.getResId());
            logger.info("=====================================");

            // 7. 插入预约表（原逻辑不变）
            int resInsertCount = resTableMapper.insertResTable(resTable);
            if (resInsertCount != 1) {
                logger.error("预约记录插入失败，resId：{}", resId);
                throw new RuntimeException("预约记录插入失败");
            }

            // 8. 根据 queryIs 控制是否插入问卷表
            if (queryIs == 1) { // 填写问卷（skipQuery=false）→ 插入问卷表
                PerQueryList queryList = new PerQueryList();
                queryList.setResId(resId);
                queryList.setUserId(userId);
                queryList.setCreateTime(new Date());
                // 问卷答案去空格+空值转null
                queryList.setAnswer1(trimOrNull(dto.getAnswer1()));
                queryList.setAnswer2(trimOrNull(dto.getAnswer2()));
                queryList.setAnswer3(trimOrNull(dto.getAnswer3()));
                queryList.setAnswer4(trimOrNull(dto.getAnswer4()));
                queryList.setAnswer5(trimOrNull(dto.getAnswer5()));
                queryList.setAnswer6(trimOrNull(dto.getAnswer6()));
                queryList.setAnswer7(trimOrNull(dto.getAnswer7()));
                queryList.setAnswer8(trimOrNull(dto.getAnswer8()));
                queryList.setAnswer9(trimOrNull(dto.getAnswer9()));
                queryList.setAnswer10(trimOrNull(dto.getAnswer10()));

                int queryInsertCount = perQueryListMapper.insertPerQueryList(queryList);
                if (queryInsertCount != 1) {
                    logger.error("问卷记录插入失败，resId：{}", resId);
                    throw new RuntimeException("问卷记录插入失败");
                }
                logger.info("问卷记录插入成功，resId：{}", resId);
            } else { // 跳过问卷（skipQuery=true）→ 不插入问卷表
                logger.info("已跳过问卷，不插入 per_query_list 表，resId：{}", resId);
            }

            // 核心逻辑：预约成功后，扣减值班表剩余名额（修复接口调用方式）
            boolean decreaseSuccess = tempWeekDailyService.decreaseRemaining(
                Long.parseLong(dto.getDoctorId().trim()), // 医生ID（前端传递）
                dto.getAppointmentDate().trim() // 预约日期（YYYY-MM-DD，对应表中 current_date_）
            );
            if (!decreaseSuccess) {
                logger.error("值班名额扣减失败，doctorId：{}，date：{}", dto.getDoctorId(), dto.getAppointmentDate());
                throw new RuntimeException("医生当天无值班记录或名额已用尽");
            }
            logger.info("值班名额扣减成功，doctorId：{}，date：{}", dto.getDoctorId(), dto.getAppointmentDate());

            logger.info("预约提交成功，resId：{}", resId);
            return true;
        } catch (ParseException e) {
            logger.error("时间格式错误", e);
            throw new RuntimeException("时间格式错误：" + e.getMessage());
        } catch (NumberFormatException e) {
            logger.error("科室ID/医生ID格式错误", e);
            throw new RuntimeException("科室ID/医生ID格式错误（需为数字）：" + e.getMessage());
        } catch (Exception e) {
            logger.error("预约提交失败", e);
            throw new RuntimeException("预约失败：" + e.getMessage());
        }
    }

    // 原有工具方法（完全保留，无修改）
    private String formatAnswer(String str) {
        if (str == null) {
            return "【null】";
        }
        String trimmed = str.trim();
        return trimmed.isEmpty() ? "【空字符串/纯空格】" : "\"" + trimmed + "\"";
    }

    private boolean isValid(String str) {
        return str != null && !str.trim().isEmpty();
    }

    private String trimOrNull(String str) {
        if (str == null) return null;
        String trimmed = str.trim();
        return trimmed.isEmpty() ? null : trimmed;
    }
}